home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 21 / Cream of the Crop 21 (Terry Blount) (October 1996).iso / os2 / e33el2.zip / emacs / 19.33 / lisp / gomoku.el < prev    next >
Lisp/Scheme  |  1996-05-23  |  45KB  |  1,183 lines

  1. ;;; gomoku.el --- Gomoku game between you and Emacs
  2.  
  3. ;; Copyright (C) 1988, 1994, 1996 Free Software Foundation, Inc.
  4.  
  5. ;; Author: Philippe Schnoebelen <phs@lifia.imag.fr>
  6. ;; Adapted-By: ESR, Daniel.Pfeiffer@Informatik.START.dbp.de
  7. ;; Keywords: games
  8.  
  9. ;; This file is part of GNU Emacs.
  10.  
  11. ;; GNU Emacs is free software; you can redistribute it and/or modify
  12. ;; it under the terms of the GNU General Public License as published by
  13. ;; the Free Software Foundation; either version 2, or (at your option)
  14. ;; any later version.
  15.  
  16. ;; GNU Emacs is distributed in the hope that it will be useful,
  17. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19. ;; GNU General Public License for more details.
  20.  
  21. ;; You should have received a copy of the GNU General Public License
  22. ;; along with GNU Emacs; see the file COPYING.  If not, write to the
  23. ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  24. ;; Boston, MA 02111-1307, USA.
  25.  
  26. ;;; Commentary:
  27.  
  28. ;; RULES:
  29. ;;
  30. ;; Gomoku is a game played between two players on a rectangular board.    Each
  31. ;; player, in turn, marks a free square of its choice. The winner is the first
  32. ;; one to mark five contiguous squares in any direction (horizontally,
  33. ;; vertically or diagonally).
  34. ;;
  35. ;; I have been told that, in "The TRUE Gomoku", some restrictions are made
  36. ;; about the squares where one may play, or else there is a known forced win
  37. ;; for the first player. This program has no such restriction, but it does not
  38. ;; know about the forced win, nor do I.     Furthermore, you probably do not know
  39. ;; it yourself :-).
  40.  
  41.  
  42. ;; There are two main places where you may want to customize the program: key
  43. ;; bindings and board display. These features are commented in the code. Go
  44. ;; and see.
  45.  
  46.  
  47. ;; HOW TO USE:
  48. ;;
  49. ;; The command "M-x gomoku" displays a
  50. ;; board, the size of which depends on the size of the current window. The
  51. ;; size of the board is easily modified by giving numeric arguments to the
  52. ;; gomoku command and/or by customizing the displaying parameters.
  53. ;;
  54. ;; Emacs plays when it is its turn. When it is your turn, just put the cursor
  55. ;; on the square where you want to play and hit RET, or X, or whatever key you
  56. ;; bind to the command gomoku-human-plays. When it is your turn, Emacs is
  57. ;; idle: you may switch buffers, read your mail, ... Just come back to the
  58. ;; *Gomoku* buffer and resume play.
  59.  
  60.  
  61. ;; ALGORITHM:
  62. ;;
  63. ;; The algorithm is briefly described in section "THE SCORE TABLE". Some
  64. ;; parameters may be modified if you want to change the style exhibited by the
  65. ;; program.
  66.  
  67. ;;; Code:
  68.  
  69. ;;;
  70. ;;; GOMOKU MODE AND KEYMAP.
  71. ;;;
  72. (defvar gomoku-mode-hook nil
  73.   "If non-nil, its value is called on entry to Gomoku mode.")
  74.  
  75. (defvar gomoku-mode-map nil
  76.   "Local keymap to use in Gomoku mode.")
  77.  
  78. (if gomoku-mode-map nil
  79.   (setq gomoku-mode-map (make-sparse-keymap))
  80.  
  81.   ;; Key bindings for cursor motion.
  82.   (define-key gomoku-mode-map "y" 'gomoku-move-nw)        ; y
  83.   (define-key gomoku-mode-map "u" 'gomoku-move-ne)        ; u
  84.   (define-key gomoku-mode-map "b" 'gomoku-move-sw)        ; b
  85.   (define-key gomoku-mode-map "n" 'gomoku-move-se)        ; n
  86.   (define-key gomoku-mode-map "h" 'backward-char)        ; h
  87.   (define-key gomoku-mode-map "l" 'forward-char)        ; l
  88.   (define-key gomoku-mode-map "j" 'gomoku-move-down)        ; j
  89.   (define-key gomoku-mode-map "k" 'gomoku-move-up)        ; k
  90.  
  91.   (define-key gomoku-mode-map [kp-7] 'gomoku-move-nw)
  92.   (define-key gomoku-mode-map [kp-9] 'gomoku-move-ne)
  93.   (define-key gomoku-mode-map [kp-1] 'gomoku-move-sw)
  94.   (define-key gomoku-mode-map [kp-3] 'gomoku-move-se)
  95.   (define-key gomoku-mode-map [kp-4] 'backward-char)
  96.   (define-key gomoku-mode-map [kp-6] 'forward-char)
  97.   (define-key gomoku-mode-map [kp-2] 'gomoku-move-down)
  98.   (define-key gomoku-mode-map [kp-8] 'gomoku-move-up)
  99.  
  100.   (define-key gomoku-mode-map "\C-n" 'gomoku-move-down)        ; C-n
  101.   (define-key gomoku-mode-map "\C-p" 'gomoku-move-up)        ; C-p
  102.  
  103.   ;; Key bindings for entering Human moves.
  104.   (define-key gomoku-mode-map "X" 'gomoku-human-plays)        ; X
  105.   (define-key gomoku-mode-map "x" 'gomoku-human-plays)        ; x
  106.   (define-key gomoku-mode-map " " 'gomoku-human-plays)        ; SPC
  107.   (define-key gomoku-mode-map "\C-m" 'gomoku-human-plays)    ; RET
  108.   (define-key gomoku-mode-map "\C-c\C-p" 'gomoku-human-plays)    ; C-c C-p
  109.   (define-key gomoku-mode-map "\C-c\C-b" 'gomoku-human-takes-back) ; C-c C-b
  110.   (define-key gomoku-mode-map "\C-c\C-r" 'gomoku-human-resigns)    ; C-c C-r
  111.   (define-key gomoku-mode-map "\C-c\C-e" 'gomoku-emacs-plays)    ; C-c C-e
  112.  
  113.   (define-key gomoku-mode-map [kp-enter] 'gomoku-human-plays)
  114.   (define-key gomoku-mode-map [insert] 'gomoku-human-plays)
  115.   (define-key gomoku-mode-map [down-mouse-1] 'gomoku-click)
  116.   (define-key gomoku-mode-map [drag-mouse-1] 'gomoku-click)
  117.   (define-key gomoku-mode-map [mouse-1] 'gomoku-click)
  118.   (define-key gomoku-mode-map [down-mouse-2] 'gomoku-click)
  119.   (define-key gomoku-mode-map [mouse-2] 'gomoku-mouse-play)
  120.   (define-key gomoku-mode-map [drag-mouse-2] 'gomoku-mouse-play)
  121.  
  122.   (substitute-key-definition 'previous-line 'gomoku-move-up
  123.                  gomoku-mode-map (current-global-map))
  124.   (substitute-key-definition 'next-line 'gomoku-move-down
  125.                  gomoku-mode-map (current-global-map))
  126.   (substitute-key-definition 'beginning-of-line 'gomoku-beginning-of-line
  127.                  gomoku-mode-map (current-global-map))
  128.   (substitute-key-definition 'end-of-line 'gomoku-end-of-line
  129.                  gomoku-mode-map (current-global-map))
  130.   (substitute-key-definition 'undo 'gomoku-human-takes-back
  131.                  gomoku-mode-map (current-global-map))
  132.   (substitute-key-definition 'advertised-undo 'gomoku-human-takes-back
  133.                  gomoku-mode-map (current-global-map)))
  134.  
  135. (defvar gomoku-emacs-won ()
  136.   "*For making font-lock use the winner's face for the line.")
  137.  
  138. (defvar gomoku-font-lock-O-face
  139.   (if window-system
  140.       (list (facemenu-get-face 'fg:red) 'bold))
  141.   "*Face to use for Emacs' O.")
  142.  
  143. (defvar gomoku-font-lock-X-face
  144.   (if window-system
  145.       (list (facemenu-get-face 'fg:green) 'bold))
  146.   "*Face to use for your X.")
  147.  
  148. (defvar gomoku-font-lock-keywords
  149.   '(("O" . gomoku-font-lock-O-face)
  150.     ("X" . gomoku-font-lock-X-face)
  151.     ("[-|/\\]" 0 (if gomoku-emacs-won
  152.              gomoku-font-lock-O-face
  153.            gomoku-font-lock-X-face)))
  154.   "*Font lock rules for Gomoku.")
  155.  
  156. (put 'gomoku-mode 'front-sticky
  157.      (put 'gomoku-mode 'rear-nonsticky '(intangible)))
  158. (put 'gomoku-mode 'intangible 1)
  159.  
  160. (defun gomoku-mode ()
  161.   "Major mode for playing Gomoku against Emacs.
  162. You and Emacs play in turn by marking a free square.  You mark it with X
  163. and Emacs marks it with O.  The winner is the first to get five contiguous
  164. marks horizontally, vertically or in diagonal.
  165.  
  166. You play by moving the cursor over the square you choose and hitting \\[gomoku-human-plays].
  167.  
  168. Other useful commands:
  169. \\{gomoku-mode-map}
  170. Entry to this mode calls the value of `gomoku-mode-hook' if that value
  171. is non-nil.  One interesting value is `turn-on-font-lock'."
  172.   (interactive)
  173.   (setq major-mode 'gomoku-mode
  174.     mode-name "Gomoku")
  175.   (gomoku-display-statistics)
  176.   (use-local-map gomoku-mode-map)
  177.   (make-local-variable 'font-lock-defaults)
  178.   (setq font-lock-defaults '(gomoku-font-lock-keywords t))
  179.   (toggle-read-only t)
  180.   (run-hooks 'gomoku-mode-hook))
  181.  
  182. ;;;
  183. ;;; THE BOARD.
  184. ;;;
  185.  
  186. ;; The board is a rectangular grid. We code empty squares with 0, X's with 1
  187. ;; and O's with 6. The rectangle is recorded in a one dimensional vector
  188. ;; containing padding squares (coded with -1). These squares allow us to
  189. ;; detect when we are trying to move out of the board.    We denote a square by
  190. ;; its (X,Y) coords, or by the INDEX corresponding to them in the vector.  The
  191. ;; leftmost topmost square has coords (1,1) and index gomoku-board-width + 2.
  192. ;; Similarly, vectors between squares may be given by two DX, DY coords or by
  193. ;; one DEPL (the difference between indexes).
  194.  
  195. (defvar gomoku-board-width nil
  196.   "Number of columns on the Gomoku board.")
  197.  
  198. (defvar gomoku-board-height nil
  199.   "Number of lines on the Gomoku board.")
  200.  
  201. (defvar gomoku-board nil
  202.   "Vector rec